home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / Sound Editor / Source / SoundEditorUtils.cpp < prev    next >
Encoding:
Text File  |  1995-12-11  |  28.7 KB  |  1,043 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        SoundEditorUtils.cpp
  3.  
  4.     Contains:    SoundEditor utility functions & classes
  5.  
  6.     Written by:    Steve Smith and Troy Gaul
  7.  
  8.     Copyright:    © 1994 - 1995 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. // -- Compiler/Preprocessor Switches --
  12.  
  13. #ifndef _COMPILERDEFS_
  14. #include "CompDefs.h"
  15. #endif
  16.  
  17. // -- OpenDoc Utilities --
  18.  
  19. #ifndef _EXCEPT_
  20. // Exceptions define several important macros (eg. CHECKENV)
  21. // which are used in the SOM method dispatch glue. If Except.h
  22. // is not included early enough, exceptions may not be thrown
  23. // correctly when returning from a SOM method with the "ev" parameter set.
  24. #include <Except.h>
  25. #endif
  26.  
  27. // -- SoundEditor Includes --
  28.  
  29. #ifndef _SOUNDEDITORUTILS_
  30. #include "SoundEditorUtils.h"
  31. #endif
  32.  
  33. #ifndef _SOUNDEDITORDEF_
  34. #include "SoundEditorDef.h"
  35. #endif
  36.  
  37. #ifndef _SOUNDEDITORGLOBALS_
  38. #include "SoundEditorGlobals.h"
  39. #endif
  40.  
  41. // -- OpenDoc Includes --
  42.  
  43. #ifndef _ODTYPES_
  44. #include <ODTypes.h>
  45. #endif
  46.  
  47. #ifndef SOM_ODArbitrator_xh
  48. #include <Arbitrat.xh>
  49. #endif
  50.  
  51. #ifndef SOM_ODDraft_xh
  52. #include <Draft.xh>
  53. #endif
  54.  
  55. #ifndef SOM_ODFrame_xh
  56. #include <Frame.xh>
  57. #endif
  58.  
  59. #ifndef SOM_ODShape_xh
  60. #include <Shape.xh>
  61. #endif
  62.  
  63. #ifndef SOM_ODStorageUnit_xh
  64. #include <StorageU.xh>
  65. #endif
  66.  
  67. // -- OpenDoc Utilities --
  68.  
  69. #ifndef _BNDNSUTL_
  70. #include <BndNSUtl.h>
  71. #endif
  72.  
  73. #ifndef _DOCUTILS_
  74. #include <DocUtils.h>
  75. #endif
  76.  
  77. #ifndef _FOCUSLIB_
  78. #include <FocusLib.h>
  79. #endif
  80.  
  81. #ifndef _INFOUTIL_
  82. #include <InfoUtil.h>
  83. #endif
  84.  
  85. #ifndef _ISOSTR_
  86. #include <ISOStr.h>
  87. #endif
  88.  
  89. #ifndef _ODMEMORY_
  90. #include <ODMemory.h>
  91. #endif
  92.  
  93. #ifndef _STORUTIL_    
  94. #include <StorUtil.h>
  95. #endif
  96.  
  97. #ifndef _TEMPITER_
  98. #include <TempIter.h>
  99. #endif
  100.  
  101. #ifndef _USERSRCM_
  102. #include <UseRsrcM.h>
  103. #endif
  104.  
  105. // --- Macintosh Includes ---
  106.  
  107. #ifndef __TYPES__
  108. #include <Types.h>
  109. #endif
  110.  
  111. #ifndef __RESOURCES__
  112. #include <Resources.h>
  113. #endif
  114.  
  115. #ifndef __TOOLUTILS__
  116. #include <ToolUtils.h>
  117. #endif
  118.  
  119. #ifndef __GXMATH__
  120. #include <GXMath.h>
  121. #endif
  122.  
  123. #ifndef __ICONS__
  124. #include <Icons.h>
  125. #endif
  126.  
  127. #ifndef _STDIO
  128. #include <stdio.h>
  129. #endif
  130.  
  131. #ifndef __TEXTUTILS__
  132. #include <TextUtils.h>        // for c2pstr
  133. #endif
  134.  
  135. #ifndef __STRINGS__
  136. #include <Strings.h>        // for c2pstr
  137. #endif
  138.  
  139. #pragma segment SoundEditorUtilities
  140.  
  141.  
  142. //====================================================================
  143. // Constants
  144. //====================================================================
  145.  
  146. const short kLeftToRight    = 0;
  147. const short kRightToLeft    = -1;
  148.  
  149.  
  150. //====================================================================
  151. // Utility Functions
  152. //====================================================================
  153.  
  154. //--------------------------------------------------------------------
  155. // GetPartName
  156. //--------------------------------------------------------------------
  157.  
  158. ODIText* GetPartName(Environment* ev, ODPart* part, ODType category)
  159. {
  160.     ASSERT(part != kODNULL, kODErrIllegalNullPartInput);
  161.  
  162.     // Get the root part of the document.
  163.     ODDraft* draft = ODGetDraft(ev,part);
  164.     TempODPart rootPart = ODAcquireRootPartOfDraft(ev, draft);
  165.     
  166.     // Get the part name.
  167.     // If we can't get a valid name for the part, we generate one using
  168.     // the user visible category name of the part's category.
  169.     TempODIText partName = ODGetPOName(ev, part, kODNULL);
  170.     
  171.     // If the part is the root of the document, return the name of the file.
  172.     if ( ODObjectsAreEqual(ev, part, rootPart) )
  173.     {
  174.         ODContainer* container = draft->GetDocument(ev)->GetContainer(ev);
  175.         TempPlatformFile file = GetPlatformFileFromContainer(ev, container);
  176.  
  177.         TempODIText fileName = file->GetName();
  178.         
  179.         // Test the file name against the part name. If the two are equivalent
  180.         // (not equal), then use the part name.
  181.         if ( !NamesAreEquivalent(ev, fileName, partName) )
  182.         {
  183.             // If the names are different, return the file name.
  184.             // (This code transfers the ODIText object to the partName tempobj)
  185.             DisposeIText(partName.DontDelete());
  186.             partName = fileName.DontDelete();
  187.         }
  188.     }
  189.     else
  190.     {
  191.         if ( partName == kODNULL || GetITextStringLength(partName) == 0 )
  192.         {
  193.             ODIText* categoryName;
  194.             ODNameSpaceManager* nsMgr = ODGetSession(ev,part)->GetNameSpaceManager(ev);
  195.             
  196.             // Get the category string from the category name space.
  197.             if ( GetUserCatFromCat(nsMgr, category, &categoryName) )
  198.             {
  199.                 // If we successfully retrieved the category user string, return it.
  200.                 // (This code transfers the ODIText object to the partName tempobj)
  201.                 DisposeIText(partName.DontDelete());
  202.                 partName = categoryName;
  203.             }
  204.             else
  205.             {
  206.     #if ODDebug
  207.                 // This should never happen. Check NMAP for errors.
  208.                 DebugStr("\pCategory NMAP bad, or Preferences corrupted.");
  209.     #else
  210.                 THROW(kODErrInvalidNSType);
  211.     #endif
  212.             }
  213.         }
  214.     }
  215.     
  216.     return partName.DontDelete();
  217. }
  218.  
  219. //--------------------------------------------------------------------
  220. // NamesAreEquivalent
  221. //--------------------------------------------------------------------
  222.  
  223. ODBoolean NamesAreEquivalent(Environment* ev, ODIText* fileName,
  224.                                         ODIText* partName)
  225. {
  226.     Str255 fileStr;
  227.     Str255 partStr;
  228.     
  229.     // If the strings are in different languages, we're done.
  230.     if ( (GetITextScriptCode(fileName) != GetITextScriptCode(partName)) ||
  231.             GetITextLangCode(fileName) != GetITextLangCode(partName) )
  232.         return kODFalse;
  233.     
  234.     GetITextPString(fileName, fileStr);
  235.     GetITextPString(partName, partStr);
  236.  
  237.     // If the string lengths are different, we're done.
  238.     if ( fileStr[0] != partStr[0] )
  239.         return kODFalse;
  240.  
  241.     // Return the Toolbox string equivalence test.
  242.     return EqualString(fileStr,partStr,kODTrue,kODTrue);
  243. }
  244.  
  245. //--------------------------------------------------------------------
  246. // GetEditorScriptLanguage
  247. //--------------------------------------------------------------------
  248.  
  249. void GetEditorScriptLanguage( Environment* ev, ODScriptCode* script,
  250.                               ODLangCode* language )
  251. {
  252.     CUsingLibraryResources res;
  253.  
  254.     Handle versHdl = GetResource('vers', 1);
  255.     
  256.     // Get the region code of the editor, otherwise use the
  257.     // region code the of the primary system script.
  258.     
  259.     long region;
  260.     if ( versHdl )
  261.     {
  262.         region = (long)(*(VersRecHndl) versHdl)->countryCode;
  263.         ReleaseResource(versHdl);
  264.     }
  265.     else
  266.     {
  267.         region = GetScriptManagerVariable(smRegionCode);
  268.     }
  269.     
  270.     // Spanish & Japanese are not actually supported by the editor.
  271.     // They are provided as examples of how to add recognition of
  272.     // additional regions (see Script.h for region codes).
  273.     
  274.     switch ((short)region) {
  275.         case verUS:
  276.             *script = smRoman;
  277.             *language = langEnglish;
  278.             break;
  279.         case verSpain:
  280.             *script = smRoman;
  281.             *language = langSpanish;
  282.             break;
  283.         case verJapan:
  284.             *script = smJapanese;
  285.             *language = langJapanese;
  286.             break;
  287.         default:
  288.             *script = smRoman;
  289.             *language = langEnglish;
  290.     }                
  291. }
  292.  
  293. //--------------------------------------------------------------------
  294. // FixedToIntRect
  295. //--------------------------------------------------------------------
  296.  
  297. void FixedToIntRect(ODRect& fixedRect, Rect& intRect)
  298. {
  299.     intRect.top        = FixedToInt(fixedRect.top);
  300.     intRect.left    = FixedToInt(fixedRect.left);
  301.     intRect.bottom    = FixedToInt(fixedRect.bottom);
  302.     intRect.right    = FixedToInt(fixedRect.right);
  303. }
  304.  
  305. //--------------------------------------------------------------------
  306. // IntToFixedRect
  307. //--------------------------------------------------------------------
  308.  
  309. void IntToFixedRect(Rect& intRect, ODRect& fixedRect)
  310. {
  311.     fixedRect.left        = ff(intRect.left);
  312.     fixedRect.top        = ff(intRect.top);
  313.     fixedRect.right        = ff(intRect.right);
  314.     fixedRect.bottom    = ff(intRect.bottom);
  315. }
  316.  
  317. //--------------------------------------------------------------------
  318. // LoadThumbnail
  319. //--------------------------------------------------------------------
  320.  
  321. void LoadThumbnail(Environment* ev, Handle* thumbnail)
  322. {
  323.     if ( *thumbnail ) return;
  324.     
  325.     CUsingLibraryResources res;
  326.     *thumbnail = (Handle) GetPicture(kThumbnailPICT);
  327. }
  328.  
  329. //--------------------------------------------------------------------
  330. // TilePartWindow
  331. //--------------------------------------------------------------------
  332.  
  333. Rect TilePartWindow(Environment* ev, Rect* facetBounds, Rect* partWindowBounds)
  334. {
  335.     const short    kWindowTilingConst    = 20;
  336.     
  337.     // Get the direction for the primary script system running on this machine.
  338.     // (Right-to-Left or Left-to-Right)
  339.     short direction = GetSysDirection();
  340.     
  341.     // The child window should be tiled from the topLeft corner of the 
  342.     // active facet whose frame is being opened.
  343.     if ( direction == kLeftToRight )
  344.     {
  345.         // Position the window rect at the top/left corner of the facet.
  346.         OffsetRect(partWindowBounds, facetBounds->left, facetBounds->top);
  347.         // Now tile the window rect down and to the right.
  348.         OffsetRect(partWindowBounds, kWindowTilingConst, kWindowTilingConst);
  349.     }
  350.     // The child window should be tiled from the topRight corner of the 
  351.     // active facet whose frame is being opened.
  352.     else if ( direction == kRightToLeft )
  353.     {
  354.         // Position the window rect at the top/right corner of the facet.
  355.         OffsetRect(partWindowBounds, (partWindowBounds->right - facetBounds->right),
  356.                     facetBounds->top);
  357.         // Now tile the window rect down and to the left.
  358.         OffsetRect(partWindowBounds, -kWindowTilingConst, kWindowTilingConst);
  359.     }
  360.     
  361.     return *partWindowBounds;
  362. }
  363.  
  364. //--------------------------------------------------------------------
  365. // CountFacets
  366. //--------------------------------------------------------------------
  367.  
  368. ODUShort CountFacets(Environment* ev, ODFrame* frame)
  369. {
  370.     ODUShort facetCount = 0;
  371.     
  372.     TempODFrameFacetIterator ffiter(ev, frame);
  373.     ODFacet*  facet = ffiter.First();
  374.     while ( ffiter.IsNotComplete() )
  375.     {
  376.         facetCount++;
  377.         facet = ffiter.Next();
  378.     }
  379.     
  380.     return facetCount;
  381. }
  382.  
  383. //------------------------------------------------------------------------------
  384. // GetIndFINF
  385. // (must have focused resource fork before calling)
  386. //------------------------------------------------------------------------------
  387.  
  388. FINF GetIndFINF(short id, short num)
  389. {
  390.     Handle    fh;
  391.     FINF    finf;
  392.  
  393.     finf.font = systemFont;
  394.     finf.face = 0;
  395.     finf.size = 0;
  396.  
  397.     if (num > 0)
  398.         if ((fh = Get1Resource('finf', id)) != nil)
  399.             if (num <= *(short *)(*fh))
  400.                 finf = ((FINFPtr)((*fh) + 2))[num - 1];
  401.  
  402.     return finf;
  403. }
  404.  
  405. //------------------------------------------------------------------------------
  406. // SetDialogDefaults
  407. // (must have focused resource fork before calling)
  408. //------------------------------------------------------------------------------
  409.  
  410. void SetDialogDefaults(DialogPtr dialog, ODUShort finfID, ODUShort index)
  411. {
  412.     FINF finf;
  413.  
  414.     SetDialogDefaultItem(dialog, ok);
  415.     SetDialogCancelItem(dialog, cancel);
  416.     
  417.     if ( finfID != 0 )
  418.     {    
  419.         SetPort(dialog);
  420.         
  421.         finf = GetIndFINF(finfID, index);
  422.         
  423.         TextFont(finf.font);
  424.         TextSize(finf.size);
  425.         TextFace(finf.face);
  426.     
  427.         DialogPeek dialogPeek = (DialogPeek) dialog;
  428.         (**(dialogPeek->textH)).txFont = finf.font;
  429.         (**(dialogPeek->textH)).txSize = finf.size;
  430.         (**(dialogPeek->textH)).txFace = finf.face;
  431.  
  432.         FontInfo finfo;
  433.         GetFontInfo(&finfo);
  434.         (**(dialogPeek->textH)).lineHeight = finfo.leading + finfo.ascent + finfo.descent;
  435.         (**(dialogPeek->textH)).fontAscent = finfo.ascent;
  436.         
  437.         TECalText(dialogPeek->textH);
  438.     }
  439. }
  440.  
  441. //------------------------------------------------------------------------------
  442. // DrawTime
  443. //------------------------------------------------------------------------------
  444.  
  445. static void GetTimeString(ODSShort numSeconds, StringPtr timeString)
  446. {
  447.     ODSShort m = numSeconds / 60;
  448.     ODSShort s = numSeconds % 60;
  449.     
  450.     Intl0Hndl intl0 = (Intl0Hndl) GetIntlResource(0);
  451.     char seperator = (**intl0).timeSep;
  452.  
  453.     sprintf((char*) timeString, "%d%c%2.2d", m, seperator, s);
  454.     c2pstr((char*) timeString);
  455. }
  456.  
  457. //------------------------------------------------------------------------------
  458. // DrawTime
  459. //------------------------------------------------------------------------------
  460.  
  461. void DrawTime( Environment* ev, ODFacet* facet, Rect& bounds,
  462.                ODSShort size, ODSShort time )
  463. {
  464.     Str255 timeString;
  465.     GetTimeString(time, timeString);
  466.     
  467.     CFocus initiateDrawing(ev, facet);
  468.         
  469.     TextFont(applFont);
  470.     TextFace(0);
  471.     TextSize(size);
  472.     TextMode(srcCopy);
  473.     
  474.     // Erase the end of the text area to avoid flicker.
  475.     ODSShort width = StringWidth(timeString);
  476.     Rect eraseBounds = bounds;
  477.     
  478.     // Base our drawing on the System direction.
  479.     eraseBounds.left += width;
  480.     MoveTo(bounds.left, bounds.bottom);
  481.     
  482.     EraseRect(&eraseBounds);
  483.  
  484.     // Draw the time.
  485.     DrawString(timeString);
  486. }
  487.  
  488. //-------------------------------------------------------------------------
  489. // Read1IndResource
  490. //-------------------------------------------------------------------------
  491.  
  492. ODHandle Read1IndResource(ResType type, short index)
  493. {
  494.     // This routine will read a resource in from the current resource
  495.     // file and into temporary memory rather than the application heap.
  496.     // The ODReadResource routine couldn't be used because it reads a
  497.     // resource from the editor's resource fork, not the current file's,
  498.     // but the code here was stolen liberally from that routine.
  499.  
  500.     ODHandle result = kODNULL; 
  501.     ODVolatile(result);
  502.     
  503.     SetResLoad(false);
  504.     Handle rsrc = Get1IndResource(type, index);
  505.     SetResLoad(true);
  506.     
  507.     if ( rsrc == kODNULL ) 
  508.     {
  509.         OSErr err = ResError();
  510.         THROW(err ? err : resNotFound);
  511.     }
  512.     
  513.     TRY
  514.         ODSize size = (*rsrc) ? GetHandleSize(rsrc) : GetResourceSizeOnDisk(rsrc);
  515.  
  516.         result = ODNewHandle(size);
  517.         void* dst = ODLockHandle(result);
  518.         
  519.         if ( *rsrc == kODNULL ) 
  520.         {
  521.             // Resource is not in memory, use partial-resource call:
  522.             ReadPartialResource(rsrc, 0, dst, size);
  523.             THROW_IF_ERROR(ResError());
  524.             ReleaseResource(rsrc);
  525.         } 
  526.         else 
  527.         {
  528.             // Resource is already in memory; just copy it:
  529.             ODBlockMove(*rsrc, dst, size);
  530.         }
  531.  
  532.         ODUnlockHandle(result);
  533.     CATCH_ALL
  534.         if ( *rsrc == kODNULL )
  535.             ReleaseResource(rsrc);
  536.         if ( result )
  537.             ODDisposeHandle(result);
  538.         RERAISE;
  539.     ENDTRY
  540.     
  541.     return result;
  542. }
  543.  
  544. //-------------------------------------------------------------------------
  545. // DrawEditorPicture
  546. //-------------------------------------------------------------------------
  547.  
  548. void DrawEditorPicture(short index, Rect& bounds)
  549. {
  550.     CUsingLibraryResources res;
  551.     
  552.     PicHandle pic = GetPicture(index);
  553.     if (pic)
  554.     {
  555.         DrawPicture(pic, &bounds);
  556.     }
  557.     else
  558.     {
  559.         THROW_IF_ERROR(ResError());
  560.         THROW(resNotFound);
  561.     }
  562. }
  563.  
  564. //=========================================================================
  565. // TempFocus
  566. //=========================================================================
  567.  
  568. //-------------------------------------------------------------------------
  569. // TempFocus::TempFocus
  570. //-------------------------------------------------------------------------
  571.  
  572. TempFocus::TempFocus( Environment*        ev, 
  573.                       ODTypeToken        focusType, 
  574.                       ODFrame*            frame )
  575. {
  576.     fEv = ev;
  577.     fFrameToFocus = frame;
  578.     fAcquired = kODFalse;
  579.     fFocusType = focusType;
  580. }
  581.     
  582. //-------------------------------------------------------------------------
  583. // TempFocus::~TempFocus
  584. //-------------------------------------------------------------------------
  585.  
  586. TempFocus::~TempFocus()
  587. {
  588.     if (fAcquired)
  589.     {
  590.         // Relinquish the clipboard focus
  591.         TempODPart tPart = fFrameToFocus->AcquirePart(fEv);
  592.         ODGetSession(fEv, tPart)->GetArbitrator(fEv)
  593.             ->RelinquishFocus(fEv, fFocusType, fFrameToFocus);
  594.     }
  595. }
  596.  
  597. //-------------------------------------------------------------------------
  598. // TempFocus::Request
  599. //-------------------------------------------------------------------------
  600.  
  601. ODBoolean TempFocus::Request()
  602. {
  603.     TempODPart tPart = fFrameToFocus->AcquirePart(fEv);
  604.     ODArbitrator* arbitrator = ODGetSession(fEv, tPart)->GetArbitrator(fEv);
  605.     
  606.     TempODFrame focusedFrame = arbitrator->AcquireFocusOwner(fEv, fFocusType);
  607.     
  608.     fAcquired = ( fAcquired
  609.                || ODObjectsAreEqual(fEv, fFrameToFocus, focusedFrame)
  610.                || arbitrator->RequestFocus(fEv, fFocusType, fFrameToFocus) );
  611.  
  612.     return fAcquired;
  613. }
  614.  
  615. //=========================================================================
  616. // TempClipboardFocus
  617. //=========================================================================
  618.  
  619. //-------------------------------------------------------------------------
  620. // TempClipboardFocus::TempClipboardFocus
  621. //-------------------------------------------------------------------------
  622.  
  623. TempClipboardFocus::TempClipboardFocus( Environment* ev, ODFrame* frame )
  624.     : TempFocus(ev, gGlobals->fClipboardFocus, frame)
  625. {
  626. }
  627.     
  628. //===========================================================================
  629. // TempHandleLockAndRememberState
  630. //===========================================================================
  631.  
  632. //-------------------------------------------------------------------------
  633. // TempHandleLockAndRememberState::TempHandleLockAndRememberState
  634. //-------------------------------------------------------------------------
  635.  
  636. TempHandleLockAndRememberState::TempHandleLockAndRememberState( ODHandle h ) 
  637.     : fHandle(h)
  638. {
  639.     if ( h )
  640.     {
  641.         fSavedState = HGetState(h);
  642.         ODLockHandle(h);
  643.     }
  644. }
  645.  
  646. //-------------------------------------------------------------------------
  647. // TempHandleLockAndRememberState::~TempHandleLockAndRememberState
  648. //-------------------------------------------------------------------------
  649.  
  650. TempHandleLockAndRememberState::~TempHandleLockAndRememberState( )
  651. {
  652.     ODHandle h = fHandle;
  653.     fHandle = (ODHandle) kODNULL;
  654.     if ( h )
  655.     {
  656.         HSetState(h, fSavedState);
  657.     }
  658. }
  659.  
  660. //=========================================================================
  661. // CFrameProxy
  662. //=========================================================================
  663.  
  664. //-------------------------------------------------------------------------
  665. // CFrameProxy::SetFrame
  666. //
  667. // Description:        The code will not affect the proxy fields unless it can
  668. //                     successfully acquire the incoming frame, it's id, and
  669. //                    the draft the frame lives in. If something goes wrong,
  670. //                    the proxy remains unchanged.
  671. //-------------------------------------------------------------------------
  672.  
  673. void CFrameProxy::SetFrame(Environment* ev, ODFrame* frame)
  674. {
  675.     ASSERT_NOT_NULL(frame);
  676.     
  677.     // Perform all the operations that can fail, first.
  678.     TempODPart    tPart    = frame->AcquirePart(ev);
  679.     ODDraft*    draft    = ODGetDraft(ev, tPart);
  680.     ODID        id        = frame->GetID(ev);
  681.     
  682.     // Release the previously referenced frame and acquire the new one.
  683.     ODTransferReference(ev, fFrame, frame);
  684.  
  685.     // If all went well, set the proxy fields.
  686.     fFrame = frame;
  687.     fID = id;
  688.     fDraft = draft;
  689. }
  690.  
  691. //-------------------------------------------------------------------------
  692. // CFrameProxy::GetFrame
  693. //-------------------------------------------------------------------------
  694.  
  695. ODFrame* CFrameProxy::GetFrame(Environment* ev)
  696. {
  697.     if ( fFrame == kODNULL )
  698.     {
  699.         TRY
  700.             TempODFrame frame = fDraft->AcquireFrame(ev, fID);
  701.             this->SetFrame(ev,frame);
  702.         CATCH_ALL
  703.             fFrame = kODNULL;
  704.             fID = kODNULLID;
  705.             RERAISE;
  706.         ENDTRY
  707.     }
  708.     return fFrame;
  709. }
  710.  
  711. //-------------------------------------------------------------------------
  712. // CFrameProxy::FrameIsLoaded
  713. //-------------------------------------------------------------------------
  714.  
  715. ODBoolean CFrameProxy::FrameIsLoaded(Environment* ev)
  716. {
  717.     ODBoolean loaded = (fFrame != kODNULL ||
  718.                         fDraft->IsValidID(ev, fID));
  719.     return loaded;
  720. }
  721.  
  722. //-------------------------------------------------------------------------
  723. // CFrameProxy::Purge
  724. //-------------------------------------------------------------------------
  725.  
  726. void CFrameProxy::Purge(Environment* ev)
  727. {
  728.     if ( fFrame != kODNULL )
  729.     {
  730.         fID = fFrame->GetID(ev);
  731.         ODReleaseObject(ev, fFrame);
  732.     }
  733. }
  734.  
  735.  
  736. //=========================================================================
  737. // CFrameInfo
  738. //=========================================================================
  739.  
  740. //-------------------------------------------------------------------------
  741. // CFrameInfo::CFrameInfo
  742. //-------------------------------------------------------------------------
  743.  
  744. CFrameInfo::CFrameInfo(ODSession* session)
  745. {
  746.     fSession = session;
  747.     fFrameActive = kODFalse;
  748.     fFrameReactivate  = kODFalse;
  749.     fShouldDisposeWindow = kODFalse;
  750.     fActiveFacet = kODNULL;
  751.     fSourceFrame = kODNULL;
  752.     fDependentFrame = kODNULL;
  753.     fPartWindowID = kODNULLID; 
  754. }
  755.  
  756. //-------------------------------------------------------------------------
  757. // CFrameInfo::~CFrameInfo
  758. //-------------------------------------------------------------------------
  759.  
  760. CFrameInfo::~CFrameInfo()
  761. {
  762.     // Deleting the proxies will release the encapsulated frames.
  763.     ODDeleteObject(fDependentFrame);
  764.     ODDeleteObject(fSourceFrame);
  765. }
  766.  
  767. //-------------------------------------------------------------------------
  768. // CFrameInfo::Externalize
  769. //-------------------------------------------------------------------------
  770.  
  771. void CFrameInfo::Externalize(Environment* ev, ODStorageUnitView* storageUnitView)
  772. {
  773.     // This method assumes that OpenDoc has passed us a storageUnitView
  774.     // that is focused to a property, but no particular value.
  775.     
  776.     ODStorageUnit* storageUnit = storageUnitView->GetStorageUnit(ev);
  777.  
  778.     this->CleanseFrameInfoProperty(ev, storageUnit);
  779.     this->ExternalizeFrameInfo(ev, storageUnit, kODNULLKey, kODNULL);
  780. }
  781.  
  782. //-------------------------------------------------------------------------
  783. // CFrameInfo::CleanseFrameInfoProperty
  784. //-------------------------------------------------------------------------
  785.  
  786. void CFrameInfo::CleanseFrameInfoProperty(Environment* ev, ODStorageUnit* storageUnit)
  787. {
  788.     ODULong numValues;
  789.     ODULong index;
  790.         
  791.     numValues = storageUnit->CountValues(ev);
  792.     
  793.     for ( index = numValues; index >= 1; index-- )
  794.     {
  795.         // Index from 1 to n through the values.
  796.         storageUnit->Focus(ev, kODNULL, kODPosSame, 
  797.                            kODNULL, index, kODPosUndefined);
  798.                                 
  799.         // Get the ISO type name for the value. The temp object
  800.         // will automatically delete the returned value when this
  801.         // scope is exited.
  802.         TempODValueType value = storageUnit->GetType(ev);
  803.         
  804.         // If the value type is not one we support, remove it.
  805.         if ( !ODISOStrEqual(value, kSoundEditorInfo) )
  806.             storageUnit->Remove(ev);
  807.     }
  808. }
  809.  
  810. //-------------------------------------------------------------------------
  811. // CFrameInfo::ExternalizeFrameInfo
  812. //-------------------------------------------------------------------------
  813.  
  814. void CFrameInfo::ExternalizeFrameInfo(Environment* ev, ODStorageUnit* storageUnit,
  815.                                         ODDraftKey key, ODFrame* scopeFrame)
  816. {
  817.     // This method behaves much the same way as the SoundEditor::ExternalizeStateInfo
  818.     // method.
  819.     
  820.     if ( storageUnit->Exists(ev, kODNULL, kSoundEditorInfo, 0) )
  821.     {
  822.         // Persistent object references are stored in a side table, rather than
  823.         // in the property/value stream. Thus, deleting the contents of a value
  824.         // will not "delete" the references previously written to that value. To
  825.         // completely "delete" all references written to the value, we must
  826.         // remove the value and add it back.
  827.  
  828.         storageUnit->Focus(ev, kODNULL, kODPosSame, kSoundEditorInfo, 0, kODPosUndefined);
  829.         storageUnit->Remove(ev);
  830.     }
  831.  
  832.     // Add a value to write the data into.
  833.     storageUnit->AddValue(ev, kSoundEditorInfo);
  834.     
  835.     // Write a weak reference to our source frame.
  836.     {
  837.         ODStorageUnitRef weakRef = {0,0,0,0};
  838.         
  839.         if ( fSourceFrame )
  840.         {
  841.             ODID        frameID = fSourceFrame->GetID();
  842.             ODID        scopeFrameID = ( scopeFrame ? scopeFrame->GetID(ev) : kODNULLID );
  843.             ODDraft*    fromDraft = fSourceFrame->GetDraft();
  844.     
  845.             // If a draft key exists, then we are being cloned to another draft.
  846.             // We must "weak" clone our display frame and reference the cloned
  847.             // frame. The part re-uses the frameID variable so there aren't two
  848.             // different GetWeakStorageUnitRef calls.
  849.             if ( key )
  850.                 frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
  851.             
  852.             // Write out weak references to each of the part's display frames.
  853.             storageUnit->GetWeakStorageUnitRef(ev, frameID, weakRef);
  854.         }
  855.         StorageUnitSetValue(storageUnit, ev, sizeof(ODStorageUnitRef), (ODPtr)&weakRef);
  856.     }
  857.     
  858.     // Write a weak reference to our dependent frame.
  859.     {
  860.         ODStorageUnitRef weakRef = {0,0,0,0};
  861.         
  862.         if ( fDependentFrame )
  863.         {
  864.             ODID        frameID = fDependentFrame->GetID();
  865.             ODID        scopeFrameID = ( scopeFrame ? scopeFrame->GetID(ev) : kODNULLID );
  866.             ODDraft*    fromDraft = fDependentFrame->GetDraft();
  867.     
  868.             // If a draft key exists, then we are being cloned to another draft.
  869.             // We must "weak" clone our display frame and reference the cloned
  870.             // frame. The part re-uses the frameID variable so there aren't two
  871.             // different GetWeakStorageUnitRef calls.
  872.             if ( key )
  873.                 frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
  874.             
  875.             // Write out weak references to each of the part's display frames.
  876.             storageUnit->GetWeakStorageUnitRef(ev, frameID, weakRef);
  877.         }
  878.         StorageUnitSetValue(storageUnit, ev, sizeof(ODStorageUnitRef), (ODPtr)&weakRef);
  879.     }
  880. }
  881.  
  882. //-------------------------------------------------------------------------
  883. // CFrameInfo::CloneInto
  884. //-------------------------------------------------------------------------
  885.  
  886. void CFrameInfo::CloneInto(Environment *ev, ODDraftKey key,
  887.                             ODStorageUnitView* storageUnitView, ODFrame* scopeFrame)
  888. {
  889.     // This method assumes that OpenDoc has passed us a storageUnitView
  890.     // that is focused to a property, but no particular value.
  891.     
  892.     ODStorageUnit* storageUnit = storageUnitView->GetStorageUnit(ev);
  893.  
  894.     if ( storageUnit->Exists(ev, kODNULL, kSoundEditorInfo, 0) == kODFalse )
  895.     {
  896.         this->ExternalizeFrameInfo(ev, storageUnit, key, scopeFrame);
  897.     }
  898. }
  899.  
  900. //-------------------------------------------------------------------------
  901. // CFrameInfo::InitFromStorage
  902. //-------------------------------------------------------------------------
  903.  
  904. void CFrameInfo::InitFromStorage(Environment* ev, ODStorageUnitView* storageUnitView)
  905. {
  906.     // This method assumes that OpenDoc has passed us a storageUnitView
  907.     // that is focused to a property, but no particular value.
  908.     
  909.     ODStorageUnit* storageUnit = storageUnitView->GetStorageUnit(ev);
  910.  
  911.     if ( storageUnit->Exists(ev, kODNULL, kSoundEditorInfo, 0) )
  912.     {
  913.         TRY
  914.             storageUnit->Focus(ev, kODNULL, kODPosSame, kSoundEditorInfo, 
  915.                                0, kODPosUndefined);
  916.     
  917.             ODStorageUnitRef weakRef = {0,0,0,0};
  918.             StorageUnitGetValue(storageUnit, ev, sizeof(ODStorageUnitRef),
  919.                                 (ODPtr)&weakRef);
  920.             
  921.             if ( storageUnit->IsValidStorageUnitRef(ev, weakRef) )
  922.             {
  923.                 // Convert the reference into a runtime id.
  924.                 ODID frameID = storageUnit->GetIDFromStorageUnitRef(ev, weakRef);
  925.             
  926.                 // Create a proxy class to support the lazy internalization.
  927.                 CFrameProxy* proxy = new CFrameProxy;
  928.                 proxy->InitFrameProxy(frameID, ODGetDraft(ev,storageUnit));
  929.             
  930.                 // Store the proxy source frame.
  931.                 fSourceFrame = proxy;
  932.             }
  933.             
  934.         CATCH_ALL
  935.             ODDeleteObject(fSourceFrame);
  936.             fSourceFrame = kODNULL;
  937.         ENDTRY
  938.  
  939.         TRY
  940.             ODStorageUnitRef weakRef = {0,0,0,0};
  941.             StorageUnitGetValue(storageUnit, ev, sizeof(ODStorageUnitRef),
  942.                                 (ODPtr)&weakRef);
  943.             
  944.             if ( storageUnit->IsValidStorageUnitRef(ev, weakRef) )
  945.             {
  946.                 // Convert the reference into a runtime id.
  947.                 ODID frameID = storageUnit->GetIDFromStorageUnitRef(ev, weakRef);
  948.             
  949.                 // Create a proxy class to support the lazy internalization.
  950.                 CFrameProxy* proxy = new CFrameProxy;
  951.                 proxy->InitFrameProxy(frameID, ODGetDraft(ev,storageUnit));
  952.             
  953.                 // Store the proxy dependent frame.
  954.                 fDependentFrame = proxy;
  955.             }
  956.             
  957.         CATCH_ALL
  958.             ODDeleteObject(fDependentFrame);
  959.             fDependentFrame = kODNULL;
  960.         ENDTRY
  961.     }
  962. }
  963.  
  964. //-------------------------------------------------------------------------
  965. // CFrameInfo::SetSourceFrame
  966. //-------------------------------------------------------------------------
  967.  
  968. void CFrameInfo::SetSourceFrame(Environment* ev, ODFrame* frame)
  969. {
  970.     if ( frame != kODNULL )
  971.     {
  972.         // Create a proxy class to support the lazy internalization.
  973.         CFrameProxy* proxy = new CFrameProxy;
  974.         proxy->InitFrameProxy(ev,frame);
  975.         
  976.         // Store the proxy source frame after clearing the old one.
  977.         ODDeleteObject(fSourceFrame);
  978.         fSourceFrame = proxy;
  979.     }
  980. }
  981.  
  982. //-------------------------------------------------------------------------
  983. // CFrameInfo::ReleaseSourceFrame
  984. //-------------------------------------------------------------------------
  985.  
  986. void CFrameInfo::ReleaseSourceFrame(Environment* ev)
  987. {
  988.     ODDeleteObject(fSourceFrame);
  989. }
  990.  
  991. //-------------------------------------------------------------------------
  992. // CFrameInfo::SetDependentFrame
  993. //-------------------------------------------------------------------------
  994.  
  995. void CFrameInfo::SetDependentFrame(Environment* ev, ODFrame* frame)
  996. {
  997.     if ( frame != kODNULL )
  998.     {
  999.         // Create a proxy class to support the lazy internalization.
  1000.         CFrameProxy* proxy = new CFrameProxy;
  1001.         proxy->InitFrameProxy(ev,frame);
  1002.         
  1003.         // Store the proxy dependent frame after clearing the old one.
  1004.         ODDeleteObject(fDependentFrame);
  1005.         fDependentFrame = proxy;
  1006.     }
  1007. }
  1008.  
  1009. //-------------------------------------------------------------------------
  1010. // CFrameInfo::ReleaseDependentFrame
  1011. //-------------------------------------------------------------------------
  1012.  
  1013. void CFrameInfo::ReleaseDependentFrame(Environment* ev)
  1014. {
  1015.     ODDeleteObject(fDependentFrame);
  1016. }
  1017.  
  1018. //-------------------------------------------------------------------------
  1019. // CFrameInfo::AcquirePartWindow
  1020. //-------------------------------------------------------------------------
  1021.  
  1022. ODWindow* CFrameInfo::AcquirePartWindow(Environment* ev)
  1023. {
  1024.     ODWindow* window = kODNULL;
  1025.     
  1026.     if ( fPartWindowID )
  1027.     {
  1028.         window = fSession->GetWindowState(ev)->AcquireWindow(ev,fPartWindowID);
  1029.         if ( !window) fPartWindowID = kODNULLID;
  1030.     }
  1031.     
  1032.     return window;
  1033. }
  1034.  
  1035. //-------------------------------------------------------------------------
  1036. // CFrameInfo::SetPartWindow
  1037. //-------------------------------------------------------------------------
  1038.  
  1039. void CFrameInfo::SetPartWindow(Environment* ev, ODWindow* window)
  1040. {
  1041.     fPartWindowID = window ? window->GetID(ev) : kODNULLID;
  1042. }
  1043.